﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;

namespace MiniCPU.Entities
{
    /// <summary>
    /// Data class representing a mutable data instance.
    /// </summary>
    public class Data
    {
        #region Variables
        /// <summary>
        /// The number value.
        /// </summary>
        private Int32 numberValue;
        #endregion

        #region Constructors
        /// <summary>
        /// Initializes a new instance of the <see cref="Data"/> class.
        /// </summary>
        public Data()
        {
            this.numberValue = 0;
        }

        /// <summary>
        /// Initializes a new instance of the <see cref="Data"/> class.
        /// </summary>
        /// <param name="value">The value.</param>
        public Data(Int32 value)
        {
            this.UpdateValue(value);
        }

        /// <summary>
        /// Initializes a new instance of the <see cref="Data"/> class.
        /// </summary>
        /// <param name="value">The value.</param>
        /// <param name="valueBase">The value base.</param>
        public Data(string value, int valueBase)
        {
            this.UpdateValue(Convert.ToInt32(value, valueBase));
        }

        /// <summary>
        /// Initializes a new instance of the <see cref="Data"/> class.
        /// </summary>
        /// <param name="value">The value.</param>
        public Data(byte value)
        {
            this.UpdateValue(Convert.ToInt32(value));
        }

        /// <summary>
        /// Initializes a new instance of the <see cref="Data"/> class.
        /// </summary>
        /// <param name="value">The value.</param>
        public Data(byte[] value)
        {
            Int32 tmpInt = Data.GetIntFromByteArray(value);

            this.UpdateValue(tmpInt);
        }
        #endregion

        #region Properties
        /// <summary>
        /// Gets or sets the int value.
        /// </summary>
        /// <value>The int value.</value>
        public int IntValue
        {
            get { return this.numberValue; }
            set { this.UpdateValue(value); }
        }

        /// <summary>
        /// Gets or sets the binary string value.
        /// </summary>
        /// <value>The binary string value.</value>
        public string BinaryStringValue
        {
            get { return this.GetString(2); }
            set { this.UpdateValue(Convert.ToInt32(value, 2)); }
        }

        /// <summary>
        /// Gets or sets the hex string value.
        /// </summary>
        /// <value>The hex string value.</value>
        public string HexStringValue
        {
            get { return this.GetString(16); }
            set { this.UpdateValue(Convert.ToInt32(value, 16)); }
        }
        #endregion

        #region Methods
        /// <summary>
        /// Gets the int from byte array.
        /// </summary>
        /// <param name="value">The value.</param>
        /// <returns>The integer value of a 4 byte array.</returns>
        protected static Int32 GetIntFromByteArray(byte[] value)
        {
            if (value.Length > 4)
            {
                throw new ArgumentOutOfRangeException();
            }

            Int32 tmpInt = 0;
            for (int i = 0; i < value.Length; i++)
            {
                tmpInt = (tmpInt << 8) | Convert.ToInt32(value);
            }

            return tmpInt;
        }

        /// <summary>
        /// Updates the value.
        /// </summary>
        /// <param name="value">The value.</param>
        protected virtual void UpdateValue(int value)
        {
            this.numberValue = value;
        }

        /// <summary>
        /// Gets the string.
        /// </summary>
        /// <param name="stringBase">The string base.</param>
        /// <returns>The string containing the value in the passed in base.</returns>
        protected virtual string GetString(int stringBase)
        {
            string tmp = Convert.ToString(this.numberValue, stringBase);
            return tmp;
        }
        #endregion
    }
}
